// Package main 提供了一个使用 Gin 框架处理参数绑定的 Web 服务器示例
// 演示了如何使用 ShouldBind 系列方法自动绑定请求参数到结构体
package main

import (
	"fmt" // 导入 fmt 包，用于格式化输出

	"github.com/gin-gonic/gin" // 导入 Gin Web 框架
)

// RunBindParamServer 初始化 Gin 路由器，注册处理参数绑定的路由，启动 Web 服务器
// 演示了如何使用 ShouldBind 系列方法自动绑定请求参数到结构体
func RunBindParamServer() {
	// 创建默认的 Gin 路由器实例
	// 包含 Logger 和 Recovery 中间件
	// Logger 中间件用于记录请求日志
	// Recovery 中间件用于从 panic 中恢复并返回 500 错误
	r := gin.Default()

	// 注册路由：GET 请求 "/" 路径处理查询参数绑定
	// 示例: ?name=张三&age=25
	r.GET("/", func(c *gin.Context) {
		// 定义 User 结构体，用于接收查询参数
		// 使用 form 标签指定字段对应的查询参数名
		type User struct {
			Name string `form:"name"` // 对应查询参数 name
			Age  int    `form:"age"`  // 对应查询参数 age
		}

		// 声明 User 结构体变量
		var user User

		// 使用 ShouldBindQuery 方法将查询参数绑定到 user 结构体
		// ShouldBindQuery 会自动解析查询参数并填充到结构体字段
		// 如果绑定成功，err 为 nil；如果绑定失败，err 包含错误信息
		err := c.ShouldBindQuery(&user)

		// 打印绑定结果和错误信息到控制台
		fmt.Println(user, err)
	})

	// 注册路由：GET 请求 "/user/:id/:name" 路径处理路径参数绑定
	// 示例: /user/1/张三
	r.GET("/user/:id/:name", func(c *gin.Context) {
		// 定义 User 结构体，用于接收路径参数
		// 使用 uri 标签指定字段对应的路径参数名
		type User struct {
			Name string `uri:"name"` // 对应路径参数 name
			ID   int    `uri:"id"`   // 对应路径参数 id
		}

		// 声明 User 结构体变量
		var user User

		// 使用 ShouldBindUri 方法将路径参数绑定到 user 结构体
		// ShouldBindUri 会自动解析路径参数并填充到结构体字段
		// 如果绑定成功，err 为 nil；如果绑定失败，err 包含错误信息
		err := c.ShouldBindUri(&user)

		// 打印绑定结果和错误信息到控制台
		fmt.Println(user, err)
	})

	// 注册路由：POST 请求 "/form" 路径处理表单参数绑定
	r.POST("/form", func(c *gin.Context) {
		// 定义 User 结构体，用于接收表单参数
		// 使用 form 标签指定字段对应的表单参数名
		type User struct {
			Name string `form:"name"` // 对应表单参数 name
			Age  int    `form:"age"`  // 对应表单参数 age
		}

		// 声明 User 结构体变量
		var user User

		// 使用 ShouldBind 方法将表单参数绑定到 user 结构体
		// ShouldBind 会根据请求的 Content-Type 自动选择绑定方式
		// 对于 application/x-www-form-urlencoded 类型，会绑定表单参数
		// 如果绑定成功，err 为 nil；如果绑定失败，err 包含错误信息
		err := c.ShouldBind(&user)

		// 打印绑定结果和错误信息到控制台
		fmt.Println(user, err)
	})

	// 注册路由：POST 请求 "/json" 路径处理 JSON 参数绑定
	r.POST("/json", func(c *gin.Context) {
		// 定义 User 结构体，用于接收 JSON 参数
		// 使用 json 标签指定字段对应的 JSON 字段名
		type User struct {
			Name string `json:"name"` // 对应 JSON 字段 name
			Age  int    `json:"age"`  // 对应 JSON 字段 age
		}

		// 声明 User 结构体变量
		var user User

		// 使用 ShouldBindJSON 方法将 JSON 参数绑定到 user 结构体
		// ShouldBindJSON 会解析请求体中的 JSON 数据并填充到结构体字段
		// 如果绑定成功，err 为 nil；如果绑定失败，err 包含错误信息
		err := c.ShouldBindJSON(&user)

		// 打印绑定结果和错误信息到控制台
		fmt.Println(user, err)
	})

	// 注册路由：POST 请求 "/header" 路径处理请求头参数绑定
	r.POST("/header", func(c *gin.Context) {
		// 定义 User 结构体，用于接收请求头参数
		// 使用 header 标签指定字段对应的请求头参数名
		type User struct {
			Name string `header:"name"` // 对应请求头参数 name
			Age  int    `header:"age"`  // 对应请求头参数 age
		}

		// 声明 User 结构体变量
		var user User

		// 使用 ShouldBindHeader 方法将请求头参数绑定到 user 结构体
		// ShouldBindHeader 会解析请求头中的参数并填充到结构体字段
		// 如果绑定成功，err 为 nil；如果绑定失败，err 包含错误信息
		err := c.ShouldBindHeader(&user)

		// 打印绑定结果和错误信息到控制台
		fmt.Println(user, err)
	})

	// 启动 HTTP 服务器，监听 8000 端口
	// 如果启动失败，会返回一个 error 类型的错误信息
	if err := r.Run(":8000"); err != nil {
		// 使用 panic 输出启动失败的错误信息
		panic(err)
	}
}
